package net.gd.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import net.gd.dao.UdfModelInfoDao;
import net.gd.dao.UdfModelLogDao;
import net.gd.domain.UdfModelInfo;
import net.gd.domain.UdfModelLog;
import net.gd.utils.Constants;
import net.gd.utils.ZeppelinApiUtils;
import net.sf.json.JSONObject;

public class ModelInfoServlet extends BaseServlet {

  private static Logger logger = Logger.getLogger(ModelInfoServlet.class);
  /**
   * 
   */
  private static final long serialVersionUID = -1686069636428282319L;

  private UdfModelInfoDao modelInfoDao;

  private UdfModelLogDao modelLogDao;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {

  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    String path = req.getRequestURI();

    logger.info("uri: " + path);
    BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream(), "UTF-8"));
    StringBuilder jsonInput = new StringBuilder();
    String line = null;
    while ((line = br.readLine()) != null) {
      jsonInput.append(line);
    }
    br.close();
    logger.info("input: " + jsonInput.toString() + " len:" + jsonInput.length());

    if (path.endsWith("create")) {
      // 1. 创建自定义模型模型
      createMode(req, resp, jsonInput.toString());
    } else if (path.endsWith("save")) {
      // 2. 新建或更新自定义模型内容
      save(req, resp, jsonInput.toString());
    } else if (path.endsWith("debug")) {
      // 3. 调式自定义模型
      debug(req, resp, jsonInput.toString());
    } else if (path.endsWith("search")) {
      // 4. 查找模型信息
      search(req, resp, jsonInput.toString());
    }
    logger.info(path + " 请求结束。");
  }

  /**
   * 查询模型信息
   * 
   * @param req
   * @param resp
   * @param input
   */
  private void search(HttpServletRequest req, HttpServletResponse resp, String input) {
    Map<String, Object> result = new HashMap<String, Object>();
    try {
      String modelId = null;
      String modelName = null;

      if (input.length() != 0) {
        JSONObject json = JSONObject.fromObject(input);
        if (json.containsKey("model_id")) {
          modelId = json.getString("model_id");
        } else if (json.containsKey("model_name")) {
          modelName = json.getString("model_name");
        }
      }
      List<UdfModelInfo> list = modelInfoDao.list(modelId, modelName);
      List<JSONObject> listJson = new ArrayList<JSONObject>();
      for (UdfModelInfo item : list) {
        listJson.add(item.toJson());
      }
      
      // 保存操作日志
      UdfModelLog log = new UdfModelLog();
      log.setModelId(modelId);
      log.setOperationType("SEARCH");
      log.setOperationDatetime(new Date());
      log.setLogId(new SimpleDateFormat(Constants.DATETIME_ID_FORMAT).format(new Date()));
      modelLogDao.save(log);
      
      result.put("code", "0");
      result.put("list", listJson);
      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
      return;
    } catch (Exception e) {
      logger.warn("Error: ", e);
      result.put("code", "1");
      result.put("msg", e.getMessage());
    }
    try {
      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
    } catch (IOException e) {
      logger.error("response error.", e);
    }
  }


  /**
   * 调式模型并向客户端返回调式结果
   * 
   * @param req
   * @param resp
   * @param input
   */
  private void debug(HttpServletRequest req, HttpServletResponse resp, String input) {
    Map<String, Object> result = new HashMap<String, Object>();
    try {
      boolean isError = false;
      String msg = "";
      JSONObject json = JSONObject.fromObject(input);
      UdfModelInfo info = null;
      if (!json.containsKey("model_id")) {
        isError = true;
        msg = "model_id is empty.";
      } else {
        info = modelInfoDao.get(json.getString("model_id"));
        if (info == null) {
          isError = true;
          msg = "model not exists.";
        }
      }

      if (isError) {
        result.put("code", "1");
        result.put("msg", msg);
        saveText4Ajax(resp, JSONObject.fromObject(result).toString());
        return;
      }

      UdfModelLog log =
          ZeppelinApiUtils.runModelContent(info.getLangType(), info.getModelContent());
      log.setModelId(info.getModelId());
      log.setOperationUser(info.getCreateUser());

      // 更新模型状态
      info.setModelStatus(log.getOperationStatus());
      modelInfoDao.saveOrUpdate(info);
      logger.info("model status update success");

      // 保存操作日志
      log.setOperationType("DEBUG");
      log.setOperationDatetime(new Date());
      log.setLogId(new SimpleDateFormat(Constants.DATETIME_ID_FORMAT).format(new Date()));
      modelLogDao.save(log);

      result.put("code", "0");
      result.put("log", log.toJson());
      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
      return;
    } catch (Exception e) {
      logger.warn("Error: ", e);
      result.put("code", "1");
      result.put("msg", e.getMessage());
    }
    try {
      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
    } catch (IOException e) {
      logger.error("response error.", e);
    }
  }

  private void save(HttpServletRequest req, HttpServletResponse resp, String input) {
    Map<String, Object> result = new HashMap<String, Object>();
    try {
      boolean isError = false;
      String msg = "";
      JSONObject json = JSONObject.fromObject(input);
      UdfModelInfo info = new UdfModelInfo();
      if (json.containsKey("model_id")) {
        info.setModelId(json.getString("model_id"));
        UdfModelInfo oldInfo = modelInfoDao.get(info.getModelId());
        if (oldInfo == null) {
          isError = true;
          msg = info.getModelId() + " UdfModelInfo not exists";
        }
      }
      if (json.containsKey("model_name")) {
        info.setModelName(json.getString("model_name"));
      }
      if (json.containsKey("lang_type")) {
        info.setLangType(json.getString("lang_type"));
      } else {
        isError = true;
        msg = "lang_type is empty.";
      }
      if (json.containsKey("model_content")) {
        info.setModelContent(json.getString("model_content"));
      } else {
        isError = true;
        msg = "model_content is empty.";
      }
      if (json.containsKey("create_user")) {
        info.setCreateUser(json.getString("create_user"));
      }
      if (json.containsKey("topic_id")) {
        info.setTopicId(json.getString("topic_id"));
      }

      if (isError) {
        result.put("code", "1");
        result.put("msg", msg);
        saveText4Ajax(resp, JSONObject.fromObject(result).toString());
        return;
      }

      String modelInfoId = modelInfoDao.saveOrUpdate(info);
      result.put("code", "0");
      result.put("model_id", modelInfoId);

      UdfModelLog log =
          ZeppelinApiUtils.runModelContent(info.getLangType(), info.getModelContent());
      log.setOperationUser(info.getCreateUser());
      log.setModelId(modelInfoId);

      // 更新模型状态
      info.setModelId(modelInfoId);
      info.setModelStatus(log.getOperationStatus());
      modelInfoDao.saveOrUpdate(info);
      logger.info("model status update success");

      result.put("log", log.toJson());

      // 保存操作日志
      if (json.containsKey("model_id")) {
        log.setOperationType("UPDATE");
      } else {
        log.setOperationType("SAVE");
      }
      log.setOperationDatetime(new Date());
      log.setLogId(new SimpleDateFormat(Constants.DATETIME_ID_FORMAT).format(new Date()));
      modelLogDao.save(log);

      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
      return;
    } catch (Exception e) {
      logger.warn("Error: ", e);
      result.put("code", "1");
      result.put("msg", e.getMessage());
    }

    try {
      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
    } catch (IOException e) {
      logger.error("response error.", e);
    }
  }

  private void createMode(HttpServletRequest req, HttpServletResponse resp, String input) {

    Map<String, Object> result = new HashMap<String, Object>();
    try {
      JSONObject json = JSONObject.fromObject(input);
      if (!json.containsKey("model_name")) {
        result.put("code", "1");
        result.put("msg", "model_name not exists.");
        saveText4Ajax(resp, JSONObject.fromObject(result).toString());
        return;
      }
      String modelId = modelInfoDao.create(json.getString("model_name"));
      if (modelId == null) {
        result.put("code", "1");
        result.put("msg", "create failed.");
      } else {
        result.put("code", "0");
        result.put("model_id", modelId);
      }

      // 保存操作日志
      UdfModelLog log = new UdfModelLog();
      log.setModelId(modelId);
      log.setOperationType("CREATE");
      log.setOperationDatetime(new Date());
      log.setLogId(new SimpleDateFormat(Constants.DATETIME_ID_FORMAT).format(new Date()));
      modelLogDao.save(log);

    } catch (Exception e) {
      logger.warn("Error: ", e);
      result.put("code", "1");
      result.put("msg", e.getMessage());
    }

    try {
      saveText4Ajax(resp, JSONObject.fromObject(result).toString());
    } catch (IOException e) {
      logger.error("response error.", e);
    }

  }

  public UdfModelInfoDao getModelInfoDao() {
    return modelInfoDao;
  }

  public void setModelInfoDao(UdfModelInfoDao modelInfoDao) {
    this.modelInfoDao = modelInfoDao;
  }

  public UdfModelLogDao getModelLogDao() {
    return modelLogDao;
  }

  public void setModelLogDao(UdfModelLogDao modelLogDao) {
    this.modelLogDao = modelLogDao;
  }

}
